//
//  MyDocument.m
//  RaiseMan
//
//  Created by Pierre Duchêne on 02/01/09.
//  Copyright IFSIC 2009 . All rights reserved.
//

#import "MyDocument.h"
#import "Person.h"

@implementation MyDocument

- (id)init
{
    self = [super init];
    if (self) {
		employees = [[NSMutableArray alloc] init];
    }
    return self;
}

- (void)dealloc
{
	[self setEmployees:nil];
	[super dealloc];
}

- (void)setEmployees:(NSMutableArray *)a
{
	if (a == employees) {
		return;
	}
	// On arrête d'observer les anciennes valeures
	for (Person *person in employees) {
		[self stopObservingPerson:person];
	}
	[a retain];
	[employees release];
	employees = a;
	// On observe les nouveaux employees
	for (Person *person in employees) {
		[self startObservingPerson:person];
	}
}

- (IBAction)createEmployee:(id)sender
{
	NSWindow *w = [tableView window];
	
	// Essaye de terminer toute modification en cours
	BOOL editingEnded = [w makeFirstResponder:w];
	if (!editingEnded) {
		NSLog(@"Impossible d'arrete la modification");
		return;
	}
	NSUndoManager *undo = [self undoManager];
	
	// une modification a-t-elle déjà eu lieu dans cet évènement?
	if ([undo groupingLevel]) {
		[undo endUndoGrouping];
		// Ouvrir un nouveau groupe.
		[undo beginUndoGrouping];
	}
	// Créer l'objet
	Person *p = [employeeController newObject];
	
	// L'ajouter au tableau de contenu de 'employeeController'
	[employeeController addObject:p];
	[p release];
	
	// Trier à nouveau (l'utilisateur à pu trier une colonne).
	[employeeController rearrangeObjects];
	
	// Obtenir le tableau trié
	NSArray *a = [employeeController arrangedObjects];
	
	// Rechercher l'objet ajouté
	int row = [a indexOfObjectIdenticalTo:p];
	NSLog(@"début de l'édition de %@ dans ligne %d",p,row);
	
	// Commencer l'édition dans la première colonne
	[tableView editColumn:0 row:row withEvent:nil select:YES];
}

- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index
{
	NSLog(@"ajout de %@ à %@",p,employees);
	// Ajouter l'opération inverse dans la pile des annulations.
	NSUndoManager *undo = [self undoManager];
	[[undo prepareWithInvocationTarget:self] removeObjectFromEmployeesAtIndex:index];
	if ([undo isUndoing]) {
		[undo setActionName:@"Insérer la personne"];
	}
	
	// Ajouter la personne dans le tableau.
	[self startObservingPerson:p];
	[employees insertObject:p atIndex:index];
}

- (void)removeObjectFromEmployeesAtIndex:(int)index
{
	// On récupère la personne pour le undoManager
	Person *p = [employees objectAtIndex:index];
	// Ajouter l'opération inverse pour le undoManager
	NSUndoManager *undo = [self undoManager];
	[[undo prepareWithInvocationTarget:self] insertObject:p inEmployeesAtIndex:index];
	// On met une étiquette sur le undo
	if ([undo isUndoing]) {
		[undo setActionName:@"Supprimer la personne"];
	}
	// Supprimer la personne
	[self stopObservingPerson:p];
	[employees removeObjectAtIndex:index];
}

- (void)startObservingPerson:(Person *)person
{
	[person addObserver:self 
			 forKeyPath:@"personName" 
				options:NSKeyValueObservingOptionOld 
				context:NULL];
	[person addObserver:self 
			 forKeyPath:@"expectedRaise" 
				options:NSKeyValueObservingOptionOld 
				context:NULL];
}

- (void)stopObservingPerson:(Person *)person
{
	[person removeObserver:self	forKeyPath:@"personName"];
	[person removeObserver:self	forKeyPath:@"expectedRaise"];
}

- (void)changeKeyPath:(NSString *)keyPath
			 ofObject:(id)obj
			  toValue:(id)newValue
{
	// setValue:forKeyPath: provoquera l'appel de la méthode KVO,
	// qui prend en charge les annulations.
	[obj setValue:newValue forKeyPath:keyPath];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
					  ofObject:(id)obj
						change:(NSDictionary *)change
					   context:(void *)context
{
	NSUndoManager *undo = [self undoManager];
	id oldValue = [change objectForKey:NSKeyValueChangeOldKey];
	
	// Les objets NSNull servent à représenter nil dansun dictionnaire
	if (oldValue == [NSNull null]) {
		oldValue = nil;
	}
	NSLog(@"ancienne valeur = %@",oldValue);
	[[undo prepareWithInvocationTarget:self] changeKeyPath:keyPath ofObject:obj toValue:oldValue];
	[undo setActionName:@"Modification"];
}

- (NSString *)windowNibName
{
    // Override returning the nib file name of the document
    // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
    return @"MyDocument";
}

- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
    [super windowControllerDidLoadNib:aController];
    // Add any code here that needs to be executed once the windowController has loaded the document's window.
}

- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
    // Insert code here to write your document to data of the specified type. If the given outError != NULL, ensure that you set *outError when returning nil.

    // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.

    // For applications targeted for Panther or earlier systems, you should use the deprecated API -dataRepresentationOfType:. In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.

    if ( outError != NULL ) {
		*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
	}
	return nil;
}

- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
    // Insert code here to read your document from the given data of the specified type.  If the given outError != NULL, ensure that you set *outError when returning NO.

    // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead. 
    
    // For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.
    
    if ( outError != NULL ) {
		*outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
	}
    return YES;
}

@end
